#region Copyright RenGuiYou. All rights reserved.
//=====================================================
// NeatlyFrameWork
// Author:      RenGuiyou
// Feedback: 	mailto:750539605@qq.com
//=====================================================
#endregion
using Cysharp.Threading.Tasks;
using Neatly.Load.Manager;
using Neatly.UI;
using UnityEngine;

namespace Neatly.Module
{
    public class SoundModule : ModuleSingleton<SoundModule>
    {
        private float m_MusicVolume;
        private float m_SoundVolume;
        private float m_VoiceVolume;
        private bool m_MusicMute;
        private bool m_SoundMute;
        private bool m_VoiceMute;
        private string m_LastMusicName = string.Empty;
        private AudioSource m_MusicSource;
        private AudioSource m_VoiceSource;
        private AudioSource[] m_SoundSources;

        public override async UniTask Init()
        {
            //获取序列号值
            m_MusicVolume = PlayerPrefsHelper.GetMusicVolume();
            m_MusicMute = PlayerPrefsHelper.GetMusicMute();
            m_SoundVolume = PlayerPrefsHelper.GetSoundVolume();
            m_SoundMute = PlayerPrefsHelper.GetSoundMute();
            //初始化音乐Source
            m_MusicSource = NeatlyFrame.Instance.audioRoot.AddComponent<AudioSource>();
            m_MusicSource.volume = m_MusicVolume;
            m_MusicSource.mute = m_MusicMute;
            m_MusicSource.loop = true;

            //初始化音效Source
            m_SoundSources = new AudioSource[NeatlyConfig.SOUND_SOURCE_COUNT];
            for (int i = 0; i < m_SoundSources.Length; i++)
            {
                m_SoundSources[i] = NeatlyFrame.Instance.audioRoot.AddComponent<AudioSource>();
                m_SoundSources[i].volume = m_SoundVolume;
                m_SoundSources[i].mute = m_SoundMute;
                m_SoundSources[i].loop = false;
            }
            //初始化voice
            m_VoiceSource = NeatlyFrame.Instance.audioRoot.AddComponent<AudioSource>();
            m_VoiceSource.volume = m_VoiceVolume;
            m_VoiceSource.mute = m_VoiceMute;
            m_VoiceSource.loop = false;
            NeatlyUI.RegisterPlaySoundAction(PlaySound);
        }

        public float MusicVolume
        {
            get => m_MusicVolume;
            set
            {
                if (!SetProperty.SetValue(ref m_MusicVolume, value)) return;
                PlayerPrefsHelper.SetMusicVolume(m_MusicVolume);
                m_MusicSource.volume = m_MusicVolume;
            }
        }
        public float SoundVolume
        {
            get => m_SoundVolume;
            set
            {
                if (!SetProperty.SetValue(ref m_SoundVolume, value)) return;
                PlayerPrefsHelper.SetSoundVolume(m_SoundVolume);
                foreach (var source in m_SoundSources)
                {
                    source.volume = m_SoundVolume;
                }
            }
        }
        public float VoiceVolume
        {
            get => m_VoiceVolume;
            set
            {
                if (!SetProperty.SetValue(ref m_VoiceVolume, value)) return;
                PlayerPrefsHelper.SetVoiceVolume(m_VoiceVolume);
                m_VoiceSource.volume = m_VoiceVolume;
            }
        }
        public bool MusicMute
        {
            get => m_MusicMute;
            set
            {
                if (!SetProperty.SetValue(ref m_MusicMute, value)) return;
                PlayerPrefsHelper.SetMusicMute(m_MusicMute);
                m_MusicSource.mute = m_MusicMute;
            }
        }
        public bool SoundMute
        {
            get => m_SoundMute;
            set
            {
                if (!SetProperty.SetValue(ref m_SoundMute, value)) return;
                PlayerPrefsHelper.SetSoundMute(m_SoundMute);
                foreach (var source in m_SoundSources)
                {
                    source.mute = m_SoundMute;
                }
            }
        }
        public bool VoiceMute
        {
            get => m_VoiceMute;
            set
            {
                if (!SetProperty.SetValue(ref m_VoiceMute, value)) return;
                PlayerPrefsHelper.SetVoiceMute(m_VoiceMute);
                m_VoiceSource.mute = m_VoiceMute;
            }
        }

        public void ReplayMusic()
        {
            m_MusicSource.Stop();
            m_MusicSource.Play();
        }

        public async void PlayMusic(string name)
        {
            if (!SetProperty.SetValue(ref m_LastMusicName, name)) return;
            var clip = await SoundLoadManager.Instance.LoadMusic(name);
            m_MusicSource.clip = clip;
            m_MusicSource.Play();
        }

        public void StopMusic()
        {
            if (!m_MusicSource.isPlaying) return;
            m_MusicSource.Stop();
            m_MusicSource.clip = null;
            m_LastMusicName = string.Empty;
        }

        public void PauseMusic()
        {
            m_MusicSource.Pause();
        }

        public void UnPauseMusic()
        {
            m_MusicSource.UnPause();
        }

        public void PlaySound(string name)
        {
            PlaySound(name, false);
        }

        public async void PlaySound(string name, bool isCompatible)
        {
            if (string.IsNullOrEmpty(name))
            {
                name = NeatlyConfig.NAME_DEFAULT_SOUND;
            }
            if (!isCompatible)
            {
                foreach (var source in m_SoundSources)
                {
                    if (!source.isPlaying || source.clip == null || !source.clip.name.Equals(name)) continue;
                    source.Stop();
                    source.Play();
                    return;
                }
            }
            int soundIndex = FindFreeSource();
            m_SoundSources[soundIndex].Stop();
            var clip = await SoundLoadManager.Instance.LoadSound(name);
            m_SoundSources[soundIndex].clip = clip;
            m_SoundSources[soundIndex].Play();
        }

        public void StopSound()
        {
            foreach (var source in m_SoundSources)
            {
                if (source.isPlaying)
                {
                    source.Stop();
                }
            }
        }

        public async void PlayVoice(string name)
        {
            var clip = await SoundLoadManager.Instance.LoadVoice(name);
            m_VoiceSource.clip = clip;
            m_VoiceSource.Play();
        }

        public void StopVoice()
        {
            m_VoiceSource.Stop();
            m_VoiceSource.clip = null;
        }

        private int FindFreeSource()
        {
            for (int i = 0; i < m_SoundSources.Length; i++)
            {
                if (!m_SoundSources[i].isPlaying)
                {
                    return i;
                }
            }
            return 0;
        }
    }
}